package sim;
/**
 * 
 */
import java.io.*;
/**
 * The Instruction Fetch stage of the pipeline. Holds the PC and the IM.
 * This is the stage that creates the instructions (from within IM)
 * @author Piotr
 *
 */
public class IFStage extends PipeStage {
	
	int pc = 0;
	private IMemory im;
	private boolean branchStatus = false; //Branch status 
	
	/**
	 * Constructs a new IFStage initialized to initPC and with IM filled by program.
	 * @param initPC The value of the initial PC.
	 * @param program The program file to be used to fill IM.
	 * @throws FileNotFoundException 
	 */
	IFStage(int initPC, File program) throws FileNotFoundException {
		pc = initPC;
		im = new IMemory(program);
	}
	
	int cycle() {
		//System.out.println(pc);
		//System.out.println(im.fetch(pc));
		if (stalled) {
			stalled = false;
		} else {
			if (branchStatus) {
				instr = null;
				branchStatus = false;
				return 0;
			} else {
				instr = im.fetch(pc++);
			}
		}
		if (instr.isNop()) {
			return 0;
		} else {
			return 1;
		}
	}
	
	/**
	 * Returns true if the pc has passed the last instruction in the program. DOES NOT check if the
	 * pipeline has emptied; a branch may change the pc and continue program execution.
	 * @return true if the pc > the address of the last instruction in the IM.
	 */
	boolean isProgramFinished() {
		if (pc > im.getHighestAddress()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * Called to have the IF stage perform a branch, given the branch target.
	 * Causes the IF stage to null out the fetched instruction on the next cycle(),
	 * introducing a bubble, and fetch the branch target on the following cycle().
	 * @param branchTarget The branch target address, absolute
	 */
	void branch(int branchTarget) {
		branchStatus = true;
		pc = branchTarget;
		
	}

}
